package com.navinfo.platform.trip.common.vehicle;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.navinfo.platform.trip.common.util.CommonUtils;
import com.navinfo.platform.trip.common.util.GsonUtils;
import com.navinfo.platform.trip.common.util.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 通过本地缓存或Redis获取车辆信息<br/>
 * 后台有kettle抽取车辆信息到Redis中，车辆参数信息全部放入Redis中，从Redis中读取
 * @author 沈东生
 */
public class VehicleInfoServiceImpl implements VehicleInfoService {
    private static Logger logger = LoggerFactory.getLogger(VehicleInfoServiceImpl.class);
    /**
     * Redis缓存
     */
    private RedisUtils redisCache;
    /**
     * 本地缓存
     */
    private LoadingCache<Long, VehicleInfo> localCache;
    /**
     * redis中存储的key前缀
     */
    static final String KEY_PREFIX = "vehicleInfo";

    @Override
    public void init(Map map) {
        redisCache = RedisUtils.getInstance(map);
        localCache = Caffeine.newBuilder()
                .refreshAfterWrite(Integer.parseInt(String.valueOf(map.get("vehicleInfo.Syn.Time"))), TimeUnit.HOURS)
                .initialCapacity(Integer.parseInt(String.valueOf(map.get("vehicleInfo.initialCapacity"))))
                .build(this::getVehicleInfo);

    }

    @Override
    public VehicleInfo get(long terminalId) {
        VehicleInfo vehicleInfo = null;
        try {
            vehicleInfo = localCache.get(terminalId);
        } catch (Exception e) {
            logger.error("获取车辆信息错误：" + terminalId, e);
        }
        return vehicleInfo;
    }

    @Override
    public void put(long terminalId, String subKey, Object value) {
        String redisKey = getKey(terminalId);
        redisCache.setHashValue(redisKey, subKey, GsonUtils.gsonString(value));
    }

    @Override
    public void reload(long terminalId){
        //从redis中获取最新的信息
        localCache.invalidate(terminalId);
    }

    /**
     * 查询redis中车辆信息，如果查询到将信息保存到本地缓存中
     * 设置最后更新时间
     * @param terminalId 通信ID
     */
    private VehicleInfo getVehicleInfo(long terminalId) {
        String redisKey = getKey(terminalId);
        VehicleInfo vehicleInfo = null;
        try {
            Map<String, String> map = redisCache.getHashValueAll(redisKey);
            if(map == null || map.size() == 0){
                vehicleInfo = new VehicleInfo();
                logger.info("获取车辆信息失败，放入一个空对象：" + terminalId);
                return vehicleInfo;
            }

            String jsonStr = GsonUtils.gsonString(map).replace("\"[", "[")
                    .replace("]\"", "]")
                    .replace("\"{", "{")
                    .replace("}\"", "}")
                    .replace("\\", "");

            if (CommonUtils.isStrNotEmpty(jsonStr)) {
                vehicleInfo = GsonUtils.gsonToBean(jsonStr, VehicleInfo.class);
                // redis的value没有存terminalId, 所以这里需要设置一下
                vehicleInfo.setTerminalId(terminalId);
                vehicleInfo.setUpdateTime(System.currentTimeMillis());

                //经济车速赋值
                double wheelRadius = vehicleInfo.getWheelRadius();
                double rearAxleSpeedRatio = vehicleInfo.getRearAxleSpeedRatio();
                double engineECORotationLow = vehicleInfo.getEngineECORotationLow();
                double engineECORotationHigh = vehicleInfo.getEngineECORotationHigh();
                double[] gearsSpeedRatio = vehicleInfo.getGearsSpeedRatio();
                double highGearSpeedRatio = 0;
                if(null!=gearsSpeedRatio && gearsSpeedRatio.length>0){
                    highGearSpeedRatio =  gearsSpeedRatio[gearsSpeedRatio.length-1];
                }
                //0.377 * 车轮半径(米) * 经济转速（RPM） / 后桥速比 / 最高档速比
                if(wheelRadius>0 && rearAxleSpeedRatio>0 && engineECORotationLow>0 && engineECORotationHigh>0 && highGearSpeedRatio>0 ){
                    vehicleInfo.setEconomicSpeedLow(0.377 * wheelRadius * engineECORotationLow / rearAxleSpeedRatio / highGearSpeedRatio);
                    vehicleInfo.setEconomicSpeedHigh(0.377 * wheelRadius * engineECORotationHigh / rearAxleSpeedRatio / highGearSpeedRatio);
                }
                logger.info("获取车辆信息成功：" + terminalId);
            }

            if (vehicleInfo == null) {
                vehicleInfo = new VehicleInfo();
                logger.info("获取车辆信息失败，放入一个空对象：" + terminalId);
            }
        } catch (Exception e){
            e.printStackTrace();
            vehicleInfo = new VehicleInfo();
            logger.info("解析车辆信息失败，放入一个空对象：" + terminalId);
        }
        return vehicleInfo;
    }


    /**
     * 获取Redis中缓存的key
     * @param terminalId 终端编号
     */
    String getKey(long terminalId) {
        return String.format("%s_%d", KEY_PREFIX, terminalId);
    }


}
